﻿#include <vector>
#include <atomic>
#include <ctime>
#include <random>
#include <shared_mutex>
#include "pydatavec.h"
#include <Python.h>
#include <thread>
#define gcbignum 10000
#define retrynum 500
pydatavec::pydatavec(unsigned long long msizemax) {
	auto a = new pyobjautoptr(Py_None);
	ptrsize = _msize(a);
	vecsizemax = msizemax*1024*1024;
}
void pydatavec::dataadd(PyObject* sou) {
	if (sou == Py_None || sou == nullptr||sou->ob_type==NULL) {
		return;
	}
	auto a = new pyobjautoptr(Py_None);
	unsigned long long mtmp = objcheck.sizeget(sou) + ptrsize;
	if (mtmp > vecsizemax) {
		exit(1);
	}
	while (vecsize + mtmp > vecsizemax) {
		veclock->lock_shared();
		vecsize -= (objcheck.sizeget(vec[0]) + ptrsize);
		std::vector<pyobjautoptr>::iterator k = vec.begin();
		veclock->unlock_shared();
		veclock->lock();
		vec.erase(k);
		veclock->unlock();
	}
	veclock->lock();
	//PyGILState_STATE gstate = PyGILState_Ensure();
	if (!(std::find(vec.begin(), vec.end(), pyobjautoptr(sou))!= vec.end())) {
		vec.push_back(pyobjautoptr(sou));
		vecsize += mtmp;
	}
	//PyGILState_Release(gstate);
	veclock->unlock();
}
PyObject* pydatavec::dataget() {
	std::default_random_engine etmp;
	etmp.seed(time(0));
	veclock->lock_shared();
	unsigned long long vecnum = vec.size();
	unsigned long long vecnumtmp = 0;
	unsigned long long numtmp = 0;
	while (vecnum <= 0) {
		vecnumtmp = vecnum;
		vecnum = vec.size();
		if (vecnum - vecnumtmp > gcbignum) {
			return Py_None;
		}
		if (numtmp > retrynum) {
			return Py_None;
		}
		numtmp++;
	}
	std::uniform_int_distribution<unsigned long long> u(0, vecnum - 1);
	auto vecchtmp = u(etmp);
	PyObject* res = vec[vecchtmp];
	veclock->unlock_shared();
	Py_INCREF(res);
	return res;
}